package com.card.server.service.impl;

import com.card.server.config.RedisService;
import com.card.server.domain.Card;
import com.card.server.domain.CardType;
import com.card.server.domain.GameInfo;
import com.card.server.enums.TimeEnum;
import com.card.server.service.IPlayCardsService;
import com.card.server.utils.GameUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author TISNIW
 * @version 1.0
 * @date 2025/5/29 0:09
 * @desc
 */
@Service
public class PlayCardsServiceImpl implements IPlayCardsService {
    @Autowired
    private GameUtil gameUtil;
    @Autowired
    private RedisService redisService;
    @Override
    public Boolean plays(List<Card> cards, String room, Integer userId) {
        String gameKey = "game:" + getRoom(room) + ":";
        GameInfo gameInfo = redisService.getCacheObject(gameKey, GameInfo.class);

        if (gameInfo == null) {
            throw new RuntimeException("房间不存在");
        }

        // 确保当前是出牌阶段
        if (gameInfo.getStatus() != 5 && gameInfo.getStatus() != 6) {
            throw new RuntimeException("当前不是出牌阶段");
        }

        // 获取当前玩家索引
        int currentPlayerIndex = -1;
        for (int i = 0; i < gameInfo.getPlayers().size(); i++) {
            if (gameInfo.getPlayers().get(i).getId().equals(userId)) {
                currentPlayerIndex = i;
                break;
            }
        }

        if (currentPlayerIndex == -1) {
            throw new RuntimeException("用户不在房间中");
        }

        // 获取当前玩家手牌
        List<Card> playerCards = gameInfo.getPlayers().get(currentPlayerIndex).getCards();

        // 检查是否拥有这些卡牌
        if (!playerCards.containsAll(cards)) {
            throw new RuntimeException("卡牌不完整或不存在");
        }

        // 获取上一轮出的牌
        List<Card> lastCards = gameInfo.getLastCards();
        CardType lastCardType = gameInfo.getCardType();

        // 判断当前出牌是否合法
        boolean isValidMove = validatePlay(gameInfo,lastCards, lastCardType, cards);

        if (!isValidMove) {
            throw new RuntimeException("出牌不符合规则");
        }

        // 移除已出卡牌
        gameInfo.setLastPlayer(currentPlayerIndex);
        playerCards.removeAll(cards);
        gameInfo.getPlayers().get(currentPlayerIndex).setCards(playerCards);

        // 设置上一手出牌
        gameInfo.setLastCards(cards);
        gameInfo.setCardType(CardType.getCardType(cards));
        gameInfo.setCurrentPlayer((currentPlayerIndex + 1) % 3); // 下一个玩家
        gameInfo.setEndTime(30L); // 重置倒计时

        // 更新 Redis 缓存
        redisService.setCacheObject(gameKey, gameInfo, TimeEnum.ONE_DAY);

        // 广播出牌信息
        gameUtil.sendPlayerMessage(gameInfo, getRoom(room));

        return true;
    }

    private boolean validatePlay(GameInfo gameInfo,List<Card> lastCards, CardType lastType, List<Card> currentCards) {
        if (gameInfo.getCurrentPlayer() == gameInfo.getLastPlayer()){
            return true;
        }
        if (lastCards == null || lastCards.isEmpty()) {
            return true;
        }

        // 当前出牌类型
        CardType currentType = CardType.getCardType(currentCards);

        // 如果是炸弹或王炸，可以压制任何牌型
        if (currentType.isBomb()) {
            return true;
        }

        // 类型必须一致
        if (currentType != lastType) {
            return false;
        }

        // 只有相同类型的牌才能比较大小
        switch (currentType) {
            case CARD_A:
                // 单张：只比较 size
                return currentCards.get(0).getSize() > lastCards.get(0).getSize();

            case CARD_AA:
                // 对子：只比较 size
                return currentCards.get(0).getSize() > lastCards.get(0).getSize();

            case CARD_AAA:
                // 三张：只比较 size
                return currentCards.get(0).getSize() > lastCards.get(0).getSize();

            case CARD_AAAB:
                // 三带一：比较三张部分的大小
                return getThreePartSize(currentCards) > getThreePartSize(lastCards);

            case CARD_AAABB:
                // 三带二：比较三张部分
                return getThreePartSize(currentCards) > getThreePartSize(lastCards);

            case CARD_ABCDE:
                // 顺子：比较最小牌
                return Collections.min(currentCards, Comparator.comparingInt(Card::getSize)).getSize() >
                        Collections.min(lastCards, Comparator.comparingInt(Card::getSize)).getSize();

            case CARD_AABB:
                // 连对：比较最小牌
                return Collections.min(currentCards, Comparator.comparingInt(Card::getSize)).getSize() >
                        Collections.min(lastCards, Comparator.comparingInt(Card::getSize)).getSize();

            default:
                return false;
        }
    }

    // 工具方法：获取三带一中的三张部分 size
    private int getThreePartSize(List<Card> cards) {
        Map<String, Integer> countMap = new HashMap<>();
        for (Card card : cards) {
            countMap.put(card.getNumber(), countMap.getOrDefault(card.getNumber(), 0) + 1);
        }

        for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
            if (entry.getValue() == 3) {
                return Integer.parseInt(entry.getKey());
            }
        }

        return 0;
    }

    private String getRoom(String key) {
        return key.substring(key.lastIndexOf(":") + 1);
    }
}
